package com.css.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

@Slf4j
public class ZipUtils {

    /**
     * 解压
     *
     * @param zipFilePath
     */
    public static ArrayList<MultipartFile> decompress(String zipFilePath) throws Exception {
        return decompress(zipFilePath, zipFilePath.replace(".zip", ""));
    }

    public static void main(String[] args) {
        try {
            decompress("D:\\地震局\\地市级政区_1726735917270.zip");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 解压
     *
     * @param zipFilePath
     * @param descDir
     */
    public static ArrayList<MultipartFile> decompress(String zipFilePath, String descDir) throws Exception {
        ArrayList<MultipartFile> list = new ArrayList<>();
        File zipFile = new File(zipFilePath);
        File pathFile = new File(descDir);

        // 创建目标目录
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }

        log.info("{} 开始解压...", zipFilePath);

        try (ZipFile zip = new ZipFile(zipFile,"GBK")) {
            Enumeration<ZipArchiveEntry> entries = zip.getEntries();

            while (entries.hasMoreElements()) {
                ZipArchiveEntry entry = entries.nextElement();

                // 如果是目录，则创建目录并跳过
                if (entry.isDirectory()) {
                    File dir = new File(descDir, entry.getName());
                    if (!dir.exists()) {
                        dir.mkdirs();
                    }
                    continue;
                }

                // 解压文件条目
                try (InputStream in = zip.getInputStream(entry);
                     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

                    byte[] buf = new byte[4096];
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        byteArrayOutputStream.write(buf, 0, len);
                    }

                    // 将解压后的数据转换为 MultipartFile
                    byte[] fileContent = byteArrayOutputStream.toByteArray();
                    MultipartFile multipartFile = new MockMultipartFile(
                            entry.getName(),
                            entry.getName(),
                            "application/octet-stream",
                            fileContent
                    );
                    list.add(multipartFile);

                    // 将文件写入目标目录
                    File outFile = new File(descDir, entry.getName());
                    File parentDir = outFile.getParentFile();
                    if (!parentDir.exists()) {
                        parentDir.mkdirs();  // 确保父目录存在
                    }
                    try (FileOutputStream fos = new FileOutputStream(outFile)) {
                        fos.write(fileContent);
                    }

                } catch (IOException e) {
                    log.error("处理条目 {} 失败", entry.getName(), e);
                    throw new Exception("解压条目失败: " + entry.getName(), e);
                }
            }

            log.info("{} 解压完毕...", zipFilePath);

        } catch (Exception e) {
            log.error("解压失败", e);
            throw new Exception("解压失败", e);
        }

        return list;
    }


    /**
     * 删除文件夹 * * @param dirPath 文件夹路径及名称 如c:/test
     */
    public static void delFolder(String dirPath) {
        try {
            delAllFile(dirPath);
            //删除完里面所有内容
            log.info("删除{}内所有文件及子目录文件", dirPath);
            File myFilePath = new File(dirPath);
            myFilePath.delete();
            //删除空文件夹
            log.info("删除目录: {}", dirPath);
        } catch (Exception e) {
            log.error("删除文件夹fail", e);
        }
    }

    /**
     * 删除文件夹里面的所有文件 (不删除最外层目录)
     *
     * @param path 文件夹路径 如 c:/test/
     */
    public static void delAllFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return;
        }
        if (!file.isDirectory()) {
            return;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                //先删除文件夹里面的文件
                delAllFile(path + "/" + tempList[i]);
                //再删除空文件夹
                delFolder(path + "/" + tempList[i]);
            }
        }
    }

    /**
     * 获取给定路径内所有是文件的绝地地址列表
     *
     * @param dir 路径
     * @return 遍历的路径集合
     */
    public static List<String> getFiles(String dir) {
        List<String> lstFiles = new ArrayList<String>();
        File file = new File(dir);
        if (!file.exists()) {
            return lstFiles;
        }
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.isDirectory()) {
                lstFiles.addAll(getFiles(f.getAbsolutePath()));
            } else {
                lstFiles.add(f.getAbsolutePath());
            }
        }
        return lstFiles;
    }
}
